package com.the_ring.chapter13.util;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;

import androidx.annotation.NonNull;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.SimpleFormatter;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class HttpUtil {

    public static final String TAG = "HttpUtil";

    public static HttpUtil INSTANCE;

    private OkHttpClient client;
    private Context context;

    public static HttpUtil getInstance(Context context) {
        if (INSTANCE == null) {
            INSTANCE = new HttpUtil(context);
        }
        return INSTANCE;
    }

    public HttpUtil(Context context) {
        client = new OkHttpClient();
        this.context = context;
    }

    /**
     * Get 方式的请求
     * @param url
     */
    public void doGet(String url) {
        // 创建一个 Get 请求
        Request request = new Request.Builder()
                // .get()  // 默认采用 GET 方式，可省略
                .header("Accept-Launguage", "zh-CN")
                .url(url)
                .build();

        // 根据请求结构创建调用对象
        Call call = client.newCall(request);

        // 加入 HTTP 请求队列，异步调用，并设置应答的回调方法
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                // 请求失败时的业务
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                // 请求成功时的业务
            }
        });
    }

    /**
     * 表单格式的 POST 请求
     * @param url
     */
    public void postForm(String url) {
        String username = "John";
        String password = "123456";

        // 创建一个表单对象
        FormBody body = new FormBody.Builder()
                .add("username", username)
                .add("password", password)
                .build();

        // 创建一个 POST 方式的请求结构
        Request request = new Request.Builder().post(body).url(url).build();

        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {

            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {

            }
        });
    }

    /**
     * JSON 格式的 POST 请求
     * 发起 POST 方式的 HTTP 请求（报文为 JSON 格式）
     * @param url
     */
    public void postJson(String url) {
        String username = "John";
        String password = "123456";
        String jsonString = "";
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", username);
            jsonObject.put("password", password);
            jsonString = jsonObject.toString();
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }

        // 创建一个 Post 方式的请求结构
        RequestBody body = RequestBody.create(jsonString,
                MediaType.parse("text/plain;charset=utf-8"));

        Request request = new Request.Builder().post(body).url(url).build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {

            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {

            }
        });
    }

    /**
     * 下载网络图片
     * @param url
     */
    public void downloadImage(String url) {
        Request request = new Request.Builder().url(url).build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                String desc = "下载网络图片报错" + e.getMessage();
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                InputStream is = response.body().byteStream();
                // 从返回的输入流中解码获得位图数据
                Bitmap bitmap = BitmapFactory.decodeStream(is);
                String mediaType = request.body().contentType().toString();
                long length = response.body().contentLength();
                String desc = String.format("文件类型 %s, 文件大小为 %d", mediaType, length);
            }
        });
    }

    /**
     * 下载网络文件
     * @param url
     */
    public void downloadFile(String url) {
        Request request = new Request.Builder().url(url).build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                String desc = "下载网络文件报错" + e.getMessage();
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                String mediaType = request.body().contentType().toString();
                long length = response.body().contentLength();
                String desc = String.format("文件类型 %s, 文件大小为 %d", mediaType, length);

                String path = String.format("%s/%s.apk",
                        context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
                        new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                // 下面从返回的输入流中读取字节数据并保存为本地文件
                try (InputStream is = response.body().byteStream();
                     FileOutputStream fos = new FileOutputStream(path)) {
                    byte[] buf = new byte[100 * 1024];
                    int sum = 0, len = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / length * 100);
                        String detail = String.format("文件保存在 %s。已下载 %d%%", path, progress);
                    }
                }
            }
        });
    }


    private List<String> mPathList = new ArrayList<>();

    /**
     * 执行文件上传操作
     * @param url
     */
    private void uploadFile(String url) {
        // 创建分段内容的建造器对象
        MultipartBody.Builder builder = new MultipartBody.Builder();
        String username = "John";
        String password = "123456";
        if (!TextUtils.isEmpty(username)) {
            // 往建造器对象中添加文本格式的分段数据
            builder.addFormDataPart("username", username);
            builder.addFormDataPart("password", password);
        }
        for (String path : mPathList) {
            // 添加多个附件
            // 根据文件路径创建文件对象
            File file = new File(path);
            // 往建造器对象中添加图像格式的分段数据
            builder.addFormDataPart("image", file.getName(), RequestBody.create(file, MediaType.parse("image/*")));
        }

        // 根据建造器生成请求结构
        RequestBody body = builder.build();

        Request request = new Request.Builder().post(body).url(url).build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(@NonNull Call call, @NonNull IOException e) {
                String desc = "调用注册接口报错：" + e.getMessage();
            }

            @Override
            public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
                String resp = response.body().toString();
                String desc = "调用注册接口返回：" + resp;
            }
        });
    }
}

